package jp.ddo.trismegistos.framework.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Stack;

public class DBConnectionPool {

	private static DBConnectionPool dBConnectionPool = null;

	private Stack<Connection> connections;

	private String driver;

	private String url;

	private String user;

	private String password;

	private int maxConnection;

	private DBConnectionPool(final String path) {

		InputStream is = null;

		try {
			is = new FileInputStream(new File(path));
			final Properties p = new Properties();
			p.load(is);
			driver = p.getProperty("driver");
			url = p.getProperty("url");
			user = p.getProperty("user");
			password = p.getProperty("password");
			maxConnection = Integer.parseInt(p.getProperty("maxConnection"));
		} catch (final IOException e) {
			e.printStackTrace();
		}
		connections = new Stack<Connection>();
		try {
			Class.forName(driver);
			for (int i = 0; i < maxConnection; i++) {
				final Connection con = DriverManager.getConnection(url, user,
						password);
				con.setAutoCommit(false);
				connections.push(con);
			}
		} catch (final Exception e) {
			System.out.println(e.getMessage());
		}
	}

	public static DBConnectionPool getInstance() {
		return getInstance(null);
	}

	public static DBConnectionPool getInstance(final String path) {
		if (dBConnectionPool == null) {
			dBConnectionPool = new DBConnectionPool(path);
		}
		return dBConnectionPool;
	}

	public synchronized Connection getConnection(final int count) {
		if (count < 1) {
			return null;
		}
		if (connections.empty() == false) {
			return connections.pop();
		} else {
			try {
				wait(100);
			} catch (final InterruptedException e) {
			}
			return getConnection(count - 1);
		}
	}

	public synchronized void releaseConnection(final Connection connection) {
		connections.push(connection);
	}

	public synchronized void closeAll() {
		for (final Connection con : connections) {
			try {
				con.close();
			} catch (final SQLException e) {
				e.printStackTrace();
			}
		}
	}
}
